// Copyright Epic Games, Inc. All Rights Reserved.

#pragma once

#include "LyraActivatableWidget.h"
#include "Containers/Ticker.h"
#include "GameplayTagContainer.h"

#include "LyraHUDLayout.generated.h"

class UCommonActivatableWidget;
class UObject;
class ULyraControllerDisconnectedScreen;

/**
 * ULyraHUDLayout
 *
 *	用于布局玩家HUD的控件（通常在体验中通过"添加控件"操作指定）
 */
UCLASS(Abstract, BlueprintType, Blueprintable, Meta = (DisplayName = "Lyra HUD Layout", Category = "Lyra|HUD"))
class ULyraHUDLayout : public ULyraActivatableWidget
{
	GENERATED_BODY()

public:

	ULyraHUDLayout(const FObjectInitializer& ObjectInitializer); // 构造函数

	/**
	 * 初始化时调用
	 */
	virtual void NativeOnInitialized() override;
	/**
	 * 销毁时调用
	 */
	virtual void NativeDestruct() override;

protected:
	/**
	 * 处理退出动作
	 */
	void HandleEscapeAction();
	
	/** 
	* 当控制器断开连接时的回调。这将检查玩家现在是否没有映射的输入设备，
	* 这意味着他们无法玩游戏。
	* 
	* 如果是这种情况，则调用 DisplayControllerDisconnectedMenu。
	*/
	void HandleInputDeviceConnectionChanged(EInputDeviceConnectionState NewConnectionState, FPlatformUserId PlatformUserId, FInputDeviceId InputDeviceId);

	/**
	* 当控制器改变其所属平台用户时的回调。我们将使用这个来检查
	* 我们是否不再需要显示"控制器断开连接"菜单
	*/
	void HandleInputDevicePairingChanged(FInputDeviceId InputDeviceId, FPlatformUserId NewUserPlatformId, FPlatformUserId OldUserPlatformId);
	
	/**
	* 通知此控件玩家的控制器状态已更改。在下一次tick时设置一个定时器来
	* 处理它们，看看我们是否需要显示/隐藏"控制器断开连接"控件。
	*/
	void NotifyControllerStateChangeForDisconnectScreen();

	/**
	 * 这将检查连接到玩家的控制器的状态。如果他们没有
	 * 任何连接到他们的控制器，那么我们应该显示断开连接菜单。如果他们确实有
	 * 连接到他们的控制器，那么如果正在显示断开连接菜单，我们可以隐藏它。
	 */
	virtual void ProcessControllerDevicesHavingChangedForDisconnectScreen();

	/**
     * 返回此平台是否支持"控制器断开连接"屏幕。 
     */
    virtual bool ShouldPlatformDisplayControllerDisconnectScreen() const;
	
	/**
	* 将 ControllerDisconnectedMenuClass 推送到菜单层 (UI.Layer.Menu)
	*/
	UFUNCTION(BlueprintNativeEvent, Category="Controller Disconnect Menu")
	void DisplayControllerDisconnectedMenu();

	/**
	* 如果控制器断开连接菜单处于活动状态，则隐藏它。
	*/
	UFUNCTION(BlueprintNativeEvent, Category="Controller Disconnect Menu")
	void HideControllerDisconnectedMenu();
	
	/**
	 * 当用户按下"暂停"或"退出"按钮时要显示的菜单
	 */
	UPROPERTY(EditDefaultsOnly) // 退出菜单类
	TSoftClassPtr<UCommonActivatableWidget> EscapeMenuClass;

	/** 
	* 如果玩家的所有控制器都断开连接，应该呈现给用户的控件。
	*/
	UPROPERTY(EditDefaultsOnly, Category="Controller Disconnect Menu") // 控制器断开连接屏幕类
	TSubclassOf<ULyraControllerDisconnectedScreen> ControllerDisconnectedScreen;

	/**
	 * 显示"控制器断开连接"屏幕所需的平台标签。
	 *
	 * 如果这些标签没有在此平台的INI文件中设置，则控制器断开连接屏幕
	 * 将永远不会显示。
	 */
	UPROPERTY(EditDefaultsOnly, Category="Controller Disconnect Menu") // 需要控制器断开连接屏幕的平台标签容器
	FGameplayTagContainer PlatformRequiresControllerDisconnectScreen;

	/** 指向活动的"控制器断开连接"菜单的指针（如果有的话） */
	UPROPERTY(Transient) // 生成的控制器断开连接屏幕
	TObjectPtr<UCommonActivatableWidget> SpawnedControllerDisconnectScreen;

	/** 来自 FSTicker 的句柄，用于当我们想要处理玩家的控制器状态时 */
	FTSTicker::FDelegateHandle RequestProcessControllerStateHandle; // 请求处理控制器状态的句柄
};